Dynomotion

Group: DynoMotion Message: 13920 From: mekanisms Date: 10/21/2016
Subject: Goniometric Motion Using Coordinated Motion
Tom (or anyone who can help),

Please take a look at the attached quick screengrab video of a model in CAD that illustrates the coordinated motion I ultimately need to achieve. 

I'm trying to mimic motion of a 2-axis goniometer system using 5-axis control. Essentially, I need to rotate about the x-axis and the y-axis.  Rotation motion will only take place in ONE axis at a time.  Although, there might be a tendency for compound rotations. 

All rotation occurs about the same center. I have attempted to do this using linear and arc coordinated motions to no avail. 

My initial approach was to use DoLinear() to handle the linear motion and use a 2nd thread to calculate the arch by computing the Z value of a sphere based on X,Y positions and commanding the Z axis with a simple Move(Z-axis,computedZ-value). That didn't work.

This will need to interact real-time with an operator so I will need to use kflop to do all the motion on-board. 
Any suggestions on how to achieve this?

Thanks in advance...

Bruk
  @@attachment@@
Group: DynoMotion Message: 13922 From: Tom Kerekes Date: 10/21/2016
Subject: Re: Goniometric Motion Using Coordinated Motion [1 Attachment]

Hi Bruk,

Interesting.  Could you provide more details on how the operator will interact with the system?  Will the Operator define a path or position to move to?  Or will it be more like jogging a single axis with an MPG?

A Move() command doesn't work well when the trajectory is rapidly changing.  You might try MoveExp().  MoveExp() often works well when an axis needs to try to follow some arbitrarily changing position.  There will be some lag.  The Tau parameter allows setting how smooth vs how little lag there is.

Regards

TK



On 10/21/2016 8:49 AM, b.sahilu@... [DynoMotion] wrote:
 

Tom (or anyone who can help),


Please take a look at the attached quick screengrab video of a model in CAD that illustrates the coordinated motion I ultimately need to achieve. 

I'm trying to mimic motion of a 2-axis goniometer system using 5-axis control. Essentially, I need to rotate about the x-axis and the y-axis.  Rotation motion will only take place in ONE axis at a time.  Although, there might be a tendency for compound rotations. 

All rotation occurs about the same center. I have attempted to do this using linear and arc coordinated motions to no avail. 

My initial approach was to use DoLinear() to handle the linear motion and use a 2nd thread to calculate the arch by computing the Z value of a sphere based on X,Y positions and commanding the Z axis with a simple Move(Z-axis,computedZ-value). That didn't work.

This will need to interact real-time with an operator so I will need to use kflop to do all the motion on-board. 
Any suggestions on how to achieve this?

Thanks in advance...

Bruk

Group: DynoMotion Message: 13925 From: mekanisms Date: 10/22/2016
Subject: Re: Goniometric Motion Using Coordinated Motion
Tom,

To better understand this is for an x-ray inspection system.  I have 2 zones. The top will have a 5-axis system to mimic a goniometer for the detector, the bottom will have a 3 axis system to control the placement of the x-ray source generator.  Thus, initially, both top and bottom are linked to move the coupled detector + x-ray source to the point of interest then, the operator will have a chance to rotate about that exact point.

The operator will be interfacing with the machine using a custom HMI linked to the Kflop.
With the detector (the grey panel looking device in the attached images an x-ray detector), the operator will be able to jog to an arbitrary X,Y location using either x-axis or y-axis jogging.  The other option is to manually enter coordinates. Both of these objectives I've been able to handle using the linear coordinated motion libraries. 

Once there, the operator will have an option to rotate the detector about the x-axis or the y-axis by +/-30 degrees in either direction. Compound angular rotations are also possible (for instance 15 degrees about x-axis AND 30 degrees about y-axis).  This sweeping action will allow the operator to view a component on a PCB board from a conical view as seen from the top in real-time. If it were actually 2 real goniometers coupled together, then it would be fairly simple to keep the surface of the detector always normal to the origin.  However, in this case, I will probably need to do a matrix-transform to track the center as it rotates about 2 planes.

The other obvious solution is to treat this as a sphere with a known radius, X and Y values and dynamically solve for Z and have the motion take course. Knowing the start point and the end point, I would think it would be practical to even generate all the points and feed it to a buffer.  From there, run the buffer and stop when the operator lifts their finger from the axial jog button.  This is the same approach as my linear jogs, I send it to the max limit relative to the respective axis and issue a stop command when the operator releases their finger from the HMI.

Hope that made a bit more sense....




  @@attachment@@
Group: DynoMotion Message: 13926 From: Tom Kerekes Date: 10/22/2016
Subject: Re: Goniometric Motion Using Coordinated Motion [2 Attachments]

That helps.

I would think that in your "phase 2 jogging mode" that the motion should really be two angles to move the position on the sphere rather than xy motions.

I'd suggest trying they MoveExp commands to all 8 axes.  The two angles would move based on the jog buttons (arbitrary speeds and directions) and the other axes (xyz top and xyz bottom) would be commanded "instantaneously" based on functions of the angles.  While in motion there would be position errors that would depend on speed of motion, accelerations and smoothing, but I would expect those to be small.  After stopping all errors would go to zero.  You didn't explain your requirements regarding accuracy and how important accuracy is an issue while moving.

Otherwise your idea of planning the 8 axes motion ahead of time might be required.  You could then use KFLOP FeedRate mechanisms to advance at different speeds, forward and backward along that path.  This approach would be limited to 1 dimensional jogging at a time.

Regards

TK


On 10/22/2016 12:03 AM, b.sahilu@... [DynoMotion] wrote:
 

Tom,


To better understand this is for an x-ray inspection system.  I have 2 zones. The top will have a 5-axis system to mimic a goniometer for the detector, the bottom will have a 3 axis system to control the placement of the x-ray source generator.  Thus, initially, both top and bottom are linked to move the coupled detector + x-ray source to the point of interest then, the operator will have a chance to rotate about that exact point.

The operator will be interfacing with the machine using a custom HMI linked to the Kflop.
With the detector (the grey panel looking device in the attached images an x-ray detector), the operator will be able to jog to an arbitrary X,Y location using either x-axis or y-axis jogging.  The other option is to manually enter coordinates. Both of these objectives I've been able to handle using the linear coordinated motion libraries. 

Once there, the operator will have an option to rotate the detector about the x-axis or the y-axis by +/-30 degrees in either direction. Compound angular rotations are also possible (for instance 15 degrees about x-axis AND 30 degrees about y-axis).  This sweeping action will allow the operator to view a component on a PCB board from a conical view as seen from the top in real-time. If it were actually 2 real goniometers coupled together, then it would be fairly simple to keep the surface of the detector always normal to the origin.  However, in this case, I will probably need to do a matrix-transform to track the center as it rotates about 2 planes.

The other obvious solution is to treat this as a sphere with a known radius, X and Y values and dynamically solve for Z and have the motion take course. Knowing the start point and the end point, I would think it would be practical to even generate all the points and feed it to a buffer.  From there, run the buffer and stop when the operator lifts their finger from the axial jog button.  This is the same approach as my linear jogs, I send it to the max limit relative to the respective axis and issue a stop command when the operator releases their finger from the HMI.

Hope that made a bit more sense....





Group: DynoMotion Message: 13988 From: mekanisms Date: 11/3/2016
Subject: Re: Goniometric Motion Using Coordinated Motion
Tom,

Just to report back. I've successfully implemented YOUR idea.  Essentially, I'm using 2 angles relative to the X and Y-axis of the origin to move the point in space representing the detector.

I'm feeding a rotation matrix twice where I rotate about X then I rotate about Y each with arbitrary degree values and getting an exact X,Y,Z position. Also, using the source (X,Y,0) position below, I can perform the translation so that it is about any arbitrary center (rather than just the origin).  Everything works.

Annnnnnnd here's my new problem.  Currently, in order to travel along the arc path of the sphere, I am allowing the operator to jog each rotation-axis by 1 degree increments.  I perform the calculations, set final destinations and issue a MoveExp() command.  You can see how jerky this can be.  Although I can have an option to have a direct angular input, often the inspection they are doing is based on what's on screen and more than likely they will be jogging ONE axis at a time.  What I was hoping to do is, to create an array that is pre-populated with thousands of X,Y,Z values and having the system fill the buffer with these points and run.

I can issue a StopCoordinatedMotion() at any point to have it stop and perhaps just move forward and backwards in the buffer (if not, I can always regenerate the points).

Soooo, yeah, how can I do that? Wait...CAN I do that?
This will then be treated as tiny line segment moves. Would it be one jerky motion?

Thanks in again Tom!
Group: DynoMotion Message: 13989 From: Tom Kerekes Date: 11/4/2016
Subject: Re: Goniometric Motion Using Coordinated Motion

Hi Bruk,

The coordinated motion idea sounds complicated and would be limited to one axis.

Have you tried increasing the Tau value on the MoveExp command to slow down and smooth out the motion?   A disadvantage here would be that the motion might deviate from the spherical somewhat when there are larger lags in the actuator positions.

Another option would be to move gradually along a trajectory (in A B Angular space) to the newly selected target position.   Maybe a simple constant angular speed would work?  Allow the operator to "step" around the target position randomly however they want in AB space.  But then only advance the currently commanded AB position gradually toward the target at some rate.  For example "steps" of 0.001 degree every millisecond.

HTH
Regards
TK



On 11/3/2016 9:58 PM, b.sahilu@... [DynoMotion] wrote:
 

Tom,


Just to report back. I've successfully implemented YOUR idea.  Essentially, I'm using 2 angles relative to the X and Y-axis of the origin to move the point in space representing the detector.

I'm feeding a rotation matrix twice where I rotate about X then I rotate about Y each with arbitrary degree values and getting an exact X,Y,Z position. Also, using the source (X,Y,0) position below, I can perform the translation so that it is about any arbitrary center (rather than just the origin).  Everything works.

Annnnnnnd here's my new problem.  Currently, in order to travel along the arc path of the sphere, I am allowing the operator to jog each rotation-axis by 1 degree increments.  I perform the calculations, set final destinations and issue a MoveExp() command.  You can see how jerky this can be.  Although I can have an option to have a direct angular input, often the inspection they are doing is based on what's on screen and more than likely they will be jogging ONE axis at a time.  What I was hoping to do is, to create an array that is pre-populated with thousands of X,Y,Z values and having the system fill the buffer with these points and run.

I can issue a StopCoordinatedMotion() at any point to have it stop and perhaps just move forward and backwards in the buffer (if not, I can always regenerate the points).

Soooo, yeah, how can I do that? Wait...CAN I do that?
This will then be treated as tiny line segment moves. Would it be one jerky motion?

Thanks in again Tom!

Group: DynoMotion Message: 13990 From: Hardy Family Date: 11/4/2016
Subject: Re: Goniometric Motion Using Coordinated Motion
Just to expand on Tom's suggestion: when we have faced this sort of dynamic motion requirement, we use the Move() function.  The nice thing is you can send another Move() command at any time and it will "interrupt" the current one.

So you could set up a thread that runs continuously in a loop, say every 10ms.  At the top of the loop, you look at where each axis currently is, and where you want them to end up.

Presumably you know the ultimate destination (user joystick position), but the aim is to get all 8 axes to that position while still following some geometric constraint, so you can't just move each axis directly to the destination because they would just linearly interpolate.

So instead, if the distance to cover would be too much for a direct move, do the math and work out the best 8-d direction to head for a short time (say 20ms, or twice your loop update interval).  Issue the Move() command for each axis to go to that way-point.  When the loop runs again, it will be half way through the previous move, but you can compute a new way-point and the old move will be redirected.

Now the Move() function will move the specified axis without regard to the others, so the total motion will not be a straight line.  It also goes at the configured max velocity for the axis.  If you want to get fancy, then use MoveAtVel() and set the velocity for each axis so that they all get to the destination point at about the same time, and you can also control the overall speed of motion.  This is what we call "poor man's coordinated motion" since it's not truly coordinated, but it gets you where you want to go and it is easy to cancel or divert.

We use this technique for touch probing, and also for some stand-alone kflop applications where the same part is made thousands of times.

Regards,
SJH




On Fri, Nov 4, 2016 at 12:39 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi Bruk,

The coordinated motion idea sounds complicated and would be limited to one axis.

Have you tried increasing the Tau value on the MoveExp command to slow down and smooth out the motion?   A disadvantage here would be that the motion might deviate from the spherical somewhat when there are larger lags in the actuator positions.

Another option would be to move gradually along a trajectory (in A B Angular space) to the newly selected target position.   Maybe a simple constant angular speed would work?  Allow the operator to "step" around the target position randomly however they want in AB space.  But then only advance the currently commanded AB position gradually toward the target at some rate.  For example "steps" of 0.001 degree every millisecond.

HTH
Regards
TK



On 11/3/2016 9:58 PM, b.sahilu@... [DynoMotion] wrote:
 

Tom,


Just to report back. I've successfully implemented YOUR idea.  Essentially, I'm using 2 angles relative to the X and Y-axis of the origin to move the point in space representing the detector.

I'm feeding a rotation matrix twice where I rotate about X then I rotate about Y each with arbitrary degree values and getting an exact X,Y,Z position. Also, using the source (X,Y,0) position below, I can perform the translation so that it is about any arbitrary center (rather than just the origin).  Everything works.

Annnnnnnd here's my new problem.  Currently, in order to travel along the arc path of the sphere, I am allowing the operator to jog each rotation-axis by 1 degree increments.  I perform the calculations, set final destinations and issue a MoveExp() command.  You can see how jerky this can be.  Although I can have an option to have a direct angular input, often the inspection they are doing is based on what's on screen and more than likely they will be jogging ONE axis at a time.  What I was hoping to do is, to create an array that is pre-populated with thousands of X,Y,Z values and having the system fill the buffer with these points and run.

I can issue a StopCoordinatedMotion() at any point to have it stop and perhaps just move forward and backwards in the buffer (if not, I can always regenerate the points).

Soooo, yeah, how can I do that? Wait...CAN I do that?
This will then be treated as tiny line segment moves. Would it be one jerky motion?

Thanks in again Tom!


Group: DynoMotion Message: 14488 From: mekanisms Date: 3/13/2017
Subject: Re: Goniometric Motion Using Coordinated Motion
Tom and SJH,

I'd like to revive this thread with a video I've got recorded of the system.

Take a look at these links:




The videos show 2 axis rotation about X and Y using matrix transforms to generate the exact (X,Y,Z) based on a fixed (0,0,Z) starting point.

As you can see, I have to step in ONE degree increments to simulate the 0-30 degree span of the top zone arc motion. That is because I'm doing linear interpolation from one point to the next.  
I'd imagine there is a simpler method to make it look much more smoother as it moves around the arc.

Thoughts?
Group: DynoMotion Message: 14548 From: mekanisms Date: 3/30/2017
Subject: Re: Goniometric Motion Using Coordinated Motion
Inspired by the Elipse.c program, I discovered how to fill a buffer.  Perhaps this was a duhhh-moment on my part, but I learned that every time I invoke DoLinear() it's actually putting a start and end point into the buffer. Anyway, follow me in this logic and see if this makes sense.

float profile_2D_mat[600][2] = {0}; //array for 2d points
float profile_3D_mat[600][3] = {0}; //array for 3d points

int rotation_radius  = 48000; //value in steps for Z-axis radius


void profile_2D_pionts(void) //fill array with points from -30.0 to +30.0 degree where degs are in 0.1 steps
{
float theta2D = 0.0;
int i,h=0,v=1;
for (i = 0; i < 601; i++)
{
theta2D = (-300 + i)/10 * (PI/180); // index 0 begins with -300
profile_2D_mat[i][h] = rotation_radius  * sinf(theta2D); //horizontal component, theta relative to Z axis
profile_2D_mat[i][v] = rotation_radius  * cosf(theta2D); //vertical component, theta relative to Z axis
}
}

//-----I can now convert all of these points on this plane by rotating every point by some theta degrees again. 

void profile_3D_axis_rot_points(float rot_theta, int rotation_axis)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  rot_theta = rot_theta * (PI/180); //convert to radians
  
  switch (rotation_axis)
  {
    case ROT_about_X:

    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][h];
      profile_3D_mat[i][y] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;

    case ROT_about_Y:
    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][y] = profile_2D_mat[i][h];
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;
  }

}

//----------now to fill a buffer---------------------

void fill_buffer(int rot_axis, int start_theta_index, int dir)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  float theta_rad = 0.0;
  OpenBuf();
  get_initial_position(); //function that grabs current pos of all axes 
  start_theta_index = start_theta_index + 300; //adjust to match array index
  //example if fill_buffer(ROT_about_X,-155,1) then start_theta_index=-155 + 300 means i=145

  switch (rot_axis)
  {
    case ROT_about_X:
    if (dir > 0) //move fwd about x-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis at pointer
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer
 
        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about x-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;


    case ROT_about_Y:
    if (dir > 0) //move fwd about y-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to rotation center
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about y-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0; //Ry

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to center 
        DoLinear(); //add linear segment to buffer 
        //set start pos to last pos for all axes

        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;
  }

}

//---------function that runs motion

int amc_linear_move(void) // 
{
    DefineCoordSystem8(axis_0DX,axis_1DY,axis_2SX,axis_3SY,axis_4SZ,axis_5RY,axis_6RX,axis_7DZ);
    VM = 600;
    A = 800;

   CS0_Flushed=TRUE;

  ExecBuf();

  while(!CheckDoneBuf() )
  {
    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button
    {
      StopCoordinatedMotion();
      while(CS0_StoppingState < 3)
      {
        //wait until stop
      }
      ClearStopImmediately();

      jogEnableFlag = 0;
      break;
    }
  }
}


//-----commanding routine
int about_x=0,about_y=1,fwd=1,rev=-1;

profile_2D_pionts(); //run once upon startup

//function if x-axis rotation selected with plane tilted by 15.5 degrees
profile_3D_axis_rot_points(155, about_x); //15.5 deg about x-axis

//move forward on profile
fill_buffer(about_x, 155, fwd);

amc_linear_move(); //execute buffer 

For simplicity and program execution efficiency, I can combine profile_3D_axis_rot_points() and fill_buffer() functions.  In fact in my code I have that. I just broke it up in this write up to make it clear.

Anyway, this approach will not work for me.  Although the motion seems to be giving me what I need, it seems that any direction of motion I select, either going forward or reverse in either about-x or about-y axis, it only goes in ONE direction.  Mainly the direction that is first initiated.  My guess is that when I stop the motion by invoking the StopCoordinatedMotion() function after releasing the button, it doesn't clear the buffer.  Any subsequent selection I make, causes the motion to continue  moving from where it left off.  I was under the impression that ClearStopImmediately() cleared any remaining elements in the buffer. 

Any thoughts?




Group: DynoMotion Message: 14549 From: mekanisms Date: 3/30/2017
Subject: Re: Goniometric Motion Using Coordinated Motion
Forgot to attach a figure showing a graphical representation of what I'm thinking.

Regards,

Bruk
  @@attachment@@
Group: DynoMotion Message: 14550 From: Tom Kerekes Date: 3/30/2017
Subject: Re: Goniometric Motion Using Coordinated Motion

Hi Bruk,

BTW it isn't clear to me why you abandoned the MoveExp method you were working on earlier.  It seems all you needed to do was to add a means of smoothly changing the angles which should have been easy to do.

But anyway regarding this new method:

If I understand correctly it is supposed to work something like this:

#1 - starting at some position the operator requests to Jog in one of 4 directions: +X -X +Y -Y

#2 - a long coordinated motion path in the selected direction is then computed and loaded into the coordinated motion buffer

#3 - The motion is commanded to execute.

#4 - Motion occurs until the operator commands to Stop

#5 - the motion Stops because a Feedhold is commanded

#6 - after coming to a Complete Stop any remaining motion is aborted and cleared

This all works the first time but when all repeated in a new direction the original direction is resumed?

Is this correct?

Regards
TK

On 3/30/2017 10:02 AM, b.sahilu@... [DynoMotion] wrote:
 

Inspired by the Elipse.c program, I discovered how to fill a buffer.  Perhaps this was a duhhh-moment on my part, but I learned that every time I invoke DoLinear() it's actually putting a start and end point into the buffer. Anyway, follow me in this logic and see if this makes sense.


float profile_2D_mat[600][2] = {0}; //array for 2d points
float profile_3D_mat[600][3] = {0}; //array for 3d points

int rotation_radius  = 48000; //value in steps for Z-axis radius


void profile_2D_pionts(void) //fill array with points from -30.0 to +30.0 degree where degs are in 0.1 steps
{
float theta2D = 0.0;
int i,h=0,v=1;
for (i = 0; i < 601; i++)
{
theta2D = (-300 + i)/10 * (PI/180); // index 0 begins with -300
profile_2D_mat[i][h] = rotation_radius  * sinf(theta2D); //horizontal component, theta relative to Z axis
profile_2D_mat[i][v] = rotation_radius  * cosf(theta2D); //vertical component, theta relative to Z axis
}
}

//-----I can now convert all of these points on this plane by rotating every point by some theta degrees again. 

void profile_3D_axis_rot_points(float rot_theta, int rotation_axis)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  rot_theta = rot_theta * (PI/180); //convert to radians
  
  switch (rotation_axis)
  {
    case ROT_about_X:

    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][h];
      profile_3D_mat[i][y] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;

    case ROT_about_Y:
    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][y] = profile_2D_mat[i][h];
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;
  }

}

//----------now to fill a buffer---------------------

void fill_buffer(int rot_axis, int start_theta_index, int dir)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  float theta_rad = 0.0;
  OpenBuf();
  get_initial_position(); //function that grabs current pos of all axes 
  start_theta_index = start_theta_index + 300; //adjust to match array index
  //example if fill_buffer(ROT_about_X,-155,1) then start_theta_index=-155 + 300 means i=145

  switch (rot_axis)
  {
    case ROT_about_X:
    if (dir > 0) //move fwd about x-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis at pointer
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer
 
        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about x-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;


    case ROT_about_Y:
    if (dir > 0) //move fwd about y-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to rotation center
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about y-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0; //Ry

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to center 
        DoLinear(); //add linear segment to buffer 
        //set start pos to last pos for all axes

        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;
  }

}

//---------function that runs motion

int amc_linear_move(void) // 
{
    DefineCoordSystem8(axis_0DX,axis_1DY,axis_2SX,axis_3SY,axis_4SZ,axis_5RY,axis_6RX,axis_7DZ);
    VM = 600;
    A = 800;

   CS0_Flushed=TRUE;

  ExecBuf();

  while(!CheckDoneBuf() )
  {
    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button
    {
      StopCoordinatedMotion();
      while(CS0_StoppingState < 3)
      {
        //wait until stop
      }
      ClearStopImmediately();

      jogEnableFlag = 0;
      break;
    }
  }
}


//-----commanding routine
int about_x=0,about_y=1,fwd=1,rev=-1;

profile_2D_pionts(); //run once upon startup

//function if x-axis rotation selected with plane tilted by 15.5 degrees
profile_3D_axis_rot_points(155, about_x); //15.5 deg about x-axis

//move forward on profile
fill_buffer(about_x, 155, fwd);

amc_linear_move(); //execute buffer 

For simplicity and program execution efficiency, I can combine profile_3D_axis_rot_points() and fill_buffer() functions.  In fact in my code I have that. I just broke it up in this write up to make it clear.

Anyway, this approach will not work for me.  Although the motion seems to be giving me what I need, it seems that any direction of motion I select, either going forward or reverse in either about-x or about-y axis, it only goes in ONE direction.  Mainly the direction that is first initiated.  My guess is that when I stop the motion by invoking the StopCoordinatedMotion() function after releasing the button, it doesn't clear the buffer.  Any subsequent selection I make, causes the motion to continue  moving from where it left off.  I was under the impression that ClearStopImmediately() cleared any remaining elements in the buffer. 

Any thoughts?





Group: DynoMotion Message: 14551 From: Bruk S Date: 3/30/2017
Subject: Re: Goniometric Motion Using Coordinated Motion
Tom,

Yes. Precisely how you have it. Explained in more simple and concise terms compared to my mumbo-jumbo, I might add.

MoveExp just didn't work for me back then, although I might revisit it again feeding it the points I've generated in this new array. It might even make indexing back and forth from the array much easier.




On Thu, Mar 30, 2017 at 3:43 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi Bruk,

BTW it isn't clear to me why you abandoned the MoveExp method you were working on earlier.  It seems all you needed to do was to add a means of smoothly changing the angles which should have been easy to do.

But anyway regarding this new method:

If I understand correctly it is supposed to work something like this:

#1 - starting at some position the operator requests to Jog in one of 4 directions: +X -X +Y -Y

#2 - a long coordinated motion path in the selected direction is then computed and loaded into the coordinated motion buffer

#3 - The motion is commanded to execute.

#4 - Motion occurs until the operator commands to Stop

#5 - the motion Stops because a Feedhold is commanded

#6 - after coming to a Complete Stop any remaining motion is aborted and cleared

This all works the first time but when all repeated in a new direction the original direction is resumed?

Is this correct?

Regards
TK


On 3/30/2017 10:02 AM, b.sahilu@... [DynoMotion] wrote:
 

Inspired by the Elipse.c program, I discovered how to fill a buffer.  Perhaps this was a duhhh-moment on my part, but I learned that every time I invoke DoLinear() it's actually putting a start and end point into the buffer. Anyway, follow me in this logic and see if this makes sense.


float profile_2D_mat[600][2] = {0}; //array for 2d points
float profile_3D_mat[600][3] = {0}; //array for 3d points

int rotation_radius  = 48000; //value in steps for Z-axis radius


void profile_2D_pionts(void) //fill array with points from -30.0 to +30.0 degree where degs are in 0.1 steps
{
float theta2D = 0.0;
int i,h=0,v=1;
for (i = 0; i < 601; i++)
{
theta2D = (-300 + i)/10 * (PI/180); // index 0 begins with -300
profile_2D_mat[i][h] = rotation_radius  * sinf(theta2D); //horizontal component, theta relative to Z axis
profile_2D_mat[i][v] = rotation_radius  * cosf(theta2D); //vertical component, theta relative to Z axis
}
}

//-----I can now convert all of these points on this plane by rotating every point by some theta degrees again. 

void profile_3D_axis_rot_points( float rot_theta, int rotation_axis)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  rot_theta = rot_theta * (PI/180); //convert to radians
  
  switch (rotation_axis)
  {
    case ROT_about_X:

    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][h];
      profile_3D_mat[i][y] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;

    case ROT_about_Y:
    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][y] = profile_2D_mat[i][h];
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;
  }

}

//----------now to fill a buffer---------------------

void fill_buffer(int rot_axis, int start_theta_index, int dir)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  float theta_rad = 0.0;
  OpenBuf();
  get_initial_position(); //function that grabs current pos of all axes 
  start_theta_index = start_theta_index + 300; //adjust to match array index
  //example if fill_buffer(ROT_about_X,- 155,1) then start_theta_index=-155 + 300 means i=145

  switch (rot_axis)
  {
    case ROT_about_X:
    if (dir > 0) //move fwd about x-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis at pointer
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer
 
        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about x-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;


    case ROT_about_Y:
    if (dir > 0) //move fwd about y-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to rotation center
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about y-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0; //Ry

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to center 
        DoLinear(); //add linear segment to buffer 
        //set start pos to last pos for all axes

        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;
  }

}

//---------function that runs motion

int amc_linear_move(void) // 
{
    DefineCoordSystem8(axis_0DX, axis_1DY,axis_2SX,axis_3SY, axis_4SZ,axis_5RY,axis_6RX, axis_7DZ);
    VM = 600;
    A = 800;

   CS0_Flushed=TRUE;

  ExecBuf();

  while(!CheckDoneBuf() )
  {
    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button
    {
      StopCoordinatedMotion();
      while(CS0_StoppingState < 3)
      {
        //wait until stop
      }
      ClearStopImmediately();

      jogEnableFlag = 0;
      break;
    }
  }
}


//-----commanding routine
int about_x=0,about_y=1,fwd=1,rev= -1;

profile_2D_pionts(); //run once upon startup

//function if x-axis rotation selected with plane tilted by 15.5 degrees
profile_3D_axis_rot_points( 155, about_x); //15.5 deg about x-axis

//move forward on profile
fill_buffer(about_x, 155, fwd);

amc_linear_move(); //execute buffer 

For simplicity and program execution efficiency, I can combine profile_3D_axis_rot_ points() and fill_buffer() functions.  In fact in my code I have that. I just broke it up in this write up to make it clear.

Anyway, this approach will not work for me.  Although the motion seems to be giving me what I need, it seems that any direction of motion I select, either going forward or reverse in either about-x or about-y axis, it only goes in ONE direction.  Mainly the direction that is first initiated.  My guess is that when I stop the motion by invoking the StopCoordinatedMotion() function after releasing the button, it doesn't clear the buffer.  Any subsequent selection I make, causes the motion to continue  moving from where it left off.  I was under the impression that ClearStopImmediately() cleared any remaining elements in the buffer. 

Any thoughts?






Group: DynoMotion Message: 14552 From: Tom Kerekes Date: 3/30/2017
Subject: Re: Goniometric Motion Using Coordinated Motion

Hi Bruk,

Looking at the code I don't see why the old motion wouldn't be cleared and new motion used.  But you left out many details.

For example I don't understand this test or see see how jogEnableFlag or the *jogVelocity could ever change:

    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button

Are you changing/executing a main program multiple times to test?

Do you have printf statements to verify ClearStopImmediately(); and OpenBuf(); are actually called between motions and in the right order?

I think:

  DefineCoordSystem8(axis_0DX,axis_1DY,axis_2SX,axis_3SY,axis_4SZ,axis_5RY,axis_6RX,axis_7DZ);
    VM = 600;
    A = 800;

should be set before calling DoLinear not afterward.

I think the DoLinear once had a bug.  Are you using the latest from 4.34h ??

Regards
TK



On 3/30/2017 3:50 PM, Bruk S b.sahilu@... [DynoMotion] wrote:
 
Tom,

Yes. Precisely how you have it. Explained in more simple and concise terms compared to my mumbo-jumbo, I might add.

MoveExp just didn't work for me back then, although I might revisit it again feeding it the points I've generated in this new array. It might even make indexing back and forth from the array much easier.




On Thu, Mar 30, 2017 at 3:43 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi Bruk,

BTW it isn't clear to me why you abandoned the MoveExp method you were working on earlier.  It seems all you needed to do was to add a means of smoothly changing the angles which should have been easy to do.

But anyway regarding this new method:

If I understand correctly it is supposed to work something like this:

#1 - starting at some position the operator requests to Jog in one of 4 directions: +X -X +Y -Y

#2 - a long coordinated motion path in the selected direction is then computed and loaded into the coordinated motion buffer

#3 - The motion is commanded to execute.

#4 - Motion occurs until the operator commands to Stop

#5 - the motion Stops because a Feedhold is commanded

#6 - after coming to a Complete Stop any remaining motion is aborted and cleared

This all works the first time but when all repeated in a new direction the original direction is resumed?

Is this correct?

Regards
TK


On 3/30/2017 10:02 AM, b.sahilu@... [DynoMotion] wrote:
 

Inspired by the Elipse.c program, I discovered how to fill a buffer.  Perhaps this was a duhhh-moment on my part, but I learned that every time I invoke DoLinear() it's actually putting a start and end point into the buffer. Anyway, follow me in this logic and see if this makes sense.


float profile_2D_mat[600][2] = {0}; //array for 2d points
float profile_3D_mat[600][3] = {0}; //array for 3d points

int rotation_radius  = 48000; //value in steps for Z-axis radius


void profile_2D_pionts(void) //fill array with points from -30.0 to +30.0 degree where degs are in 0.1 steps
{
float theta2D = 0.0;
int i,h=0,v=1;
for (i = 0; i < 601; i++)
{
theta2D = (-300 + i)/10 * (PI/180); // index 0 begins with -300
profile_2D_mat[i][h] = rotation_radius  * sinf(theta2D); //horizontal component, theta relative to Z axis
profile_2D_mat[i][v] = rotation_radius  * cosf(theta2D); //vertical component, theta relative to Z axis
}
}

//-----I can now convert all of these points on this plane by rotating every point by some theta degrees again. 

void profile_3D_axis_rot_points( float rot_theta, int rotation_axis)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  rot_theta = rot_theta * (PI/180); //convert to radians
  
  switch (rotation_axis)
  {
    case ROT_about_X:

    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][h];
      profile_3D_mat[i][y] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;

    case ROT_about_Y:
    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][y] = profile_2D_mat[i][h];
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;
  }

}

//----------now to fill a buffer---------------------

void fill_buffer(int rot_axis, int start_theta_index, int dir)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  float theta_rad = 0.0;
  OpenBuf();
  get_initial_position(); //function that grabs current pos of all axes 
  start_theta_index = start_theta_index + 300; //adjust to match array index
  //example if fill_buffer(ROT_about_X,- 155,1) then start_theta_index=-155 + 300 means i=145

  switch (rot_axis)
  {
    case ROT_about_X:
    if (dir > 0) //move fwd about x-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis at pointer
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer
 
        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about x-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;


    case ROT_about_Y:
    if (dir > 0) //move fwd about y-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to rotation center
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about y-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0; //Ry

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to center 
        DoLinear(); //add linear segment to buffer 
        //set start pos to last pos for all axes

        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;
  }

}

//---------function that runs motion

int amc_linear_move(void) // 
{
    DefineCoordSystem8(axis_0DX, axis_1DY,axis_2SX,axis_3SY, axis_4SZ,axis_5RY,axis_6RX, axis_7DZ);
    VM = 600;
    A = 800;

   CS0_Flushed=TRUE;

  ExecBuf();

  while(!CheckDoneBuf() )
  {
    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button
    {
      StopCoordinatedMotion();
      while(CS0_StoppingState < 3)
      {
        //wait until stop
      }
      ClearStopImmediately();

      jogEnableFlag = 0;
      break;
    }
  }
}


//-----commanding routine
int about_x=0,about_y=1,fwd=1,rev= -1;

profile_2D_pionts(); //run once upon startup

//function if x-axis rotation selected with plane tilted by 15.5 degrees
profile_3D_axis_rot_points( 155, about_x); //15.5 deg about x-axis

//move forward on profile
fill_buffer(about_x, 155, fwd);

amc_linear_move(); //execute buffer 

For simplicity and program execution efficiency, I can combine profile_3D_axis_rot_ points() and fill_buffer() functions.  In fact in my code I have that. I just broke it up in this write up to make it clear.

Anyway, this approach will not work for me.  Although the motion seems to be giving me what I need, it seems that any direction of motion I select, either going forward or reverse in either about-x or about-y axis, it only goes in ONE direction.  Mainly the direction that is first initiated.  My guess is that when I stop the motion by invoking the StopCoordinatedMotion() function after releasing the button, it doesn't clear the buffer.  Any subsequent selection I make, causes the motion to continue  moving from where it left off.  I was under the impression that ClearStopImmediately() cleared any remaining elements in the buffer. 

Any thoughts?







Group: DynoMotion Message: 14553 From: Bruk S Date: 3/30/2017
Subject: Re: Goniometric Motion Using Coordinated Motion
Tom,

I'll do some debugging statements to confirm they are being called. And no, I'm still using 4.34a or something like that.
I'll try loading 4.34h and test.

Thanks! 

On Thu, Mar 30, 2017 at 4:17 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi Bruk,

Looking at the code I don't see why the old motion wouldn't be cleared and new motion used.  But you left out many details.

For example I don't understand this test or see see how jogEnableFlag or the *jogVelocity could ever change:

    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button

Are you changing/executing a main program multiple times to test?

Do you have printf statements to verify ClearStopImmediately(); and OpenBuf(); are actually called between motions and in the right order?

I think:

  DefineCoordSystem8(axis_0DX,ax is_1DY,axis_2SX,axis_3SY,axis_ 4SZ,axis_5RY,axis_6RX,axis_ 7DZ);
    VM = 600;
    A = 800;

should be set before calling DoLinear not afterward.

I think the DoLinear once had a bug.  Are you using the latest from 4.34h ??

Regards
TK



On 3/30/2017 3:50 PM, Bruk S b.sahilu@... [DynoMotion] wrote:
 
Tom,

Yes. Precisely how you have it. Explained in more simple and concise terms compared to my mumbo-jumbo, I might add.

MoveExp just didn't work for me back then, although I might revisit it again feeding it the points I've generated in this new array. It might even make indexing back and forth from the array much easier.




On Thu, Mar 30, 2017 at 3:43 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi Bruk,

BTW it isn't clear to me why you abandoned the MoveExp method you were working on earlier.  It seems all you needed to do was to add a means of smoothly changing the angles which should have been easy to do.

But anyway regarding this new method:

If I understand correctly it is supposed to work something like this:

#1 - starting at some position the operator requests to Jog in one of 4 directions: +X -X +Y -Y

#2 - a long coordinated motion path in the selected direction is then computed and loaded into the coordinated motion buffer

#3 - The motion is commanded to execute.

#4 - Motion occurs until the operator commands to Stop

#5 - the motion Stops because a Feedhold is commanded

#6 - after coming to a Complete Stop any remaining motion is aborted and cleared

This all works the first time but when all repeated in a new direction the original direction is resumed?

Is this correct?

Regards
TK


On 3/30/2017 10:02 AM, b.sahilu@... [DynoMotion] wrote:
 

Inspired by the Elipse.c program, I discovered how to fill a buffer.  Perhaps this was a duhhh-moment on my part, but I learned that every time I invoke DoLinear() it's actually putting a start and end point into the buffer. Anyway, follow me in this logic and see if this makes sense.


float profile_2D_mat[600][2] = {0}; //array for 2d points
float profile_3D_mat[600][3] = {0}; //array for 3d points

int rotation_radius  = 48000; //value in steps for Z-axis radius


void profile_2D_pionts(void) //fill array with points from -30.0 to +30.0 degree where degs are in 0.1 steps
{
float theta2D = 0.0;
int i,h=0,v=1;
for (i = 0; i < 601; i++)
{
theta2D = (-300 + i)/10 * (PI/180); // index 0 begins with -300
profile_2D_mat[i][h] = rotation_radius  * sinf(theta2D); //horizontal component, theta relative to Z axis
profile_2D_mat[i][v] = rotation_radius  * cosf(theta2D); //vertical component, theta relative to Z axis
}
}

//-----I can now convert all of these points on this plane by rotating every point by some theta degrees again. 

void profile_3D_axis_rot_points(flo at rot_theta, int rotation_axis)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  rot_theta = rot_theta * (PI/180); //convert to radians
  
  switch (rotation_axis)
  {
    case ROT_about_X:

    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][h];
      profile_3D_mat[i][y] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;

    case ROT_about_Y:
    for (i = 0; i < 601; i++)
  {
      profile_3D_mat[i][x] = profile_2D_mat[i][v] * sinf(rot_theta);
      profile_3D_mat[i][y] = profile_2D_mat[i][h];
      profile_3D_mat[i][z] = profile_2D_mat[i][v] * cosf(rot_theta);
    }
    break;
  }

}

//----------now to fill a buffer---------------------

void fill_buffer(int rot_axis, int start_theta_index, int dir)
{
  int x=0,y=1,z=2;
  int h=0,v=1,i;
  
  float theta_rad = 0.0;
  OpenBuf();
  get_initial_position(); //function that grabs current pos of all axes 
  start_theta_index = start_theta_index + 300; //adjust to match array index
  //example if fill_buffer(ROT_about_X,-15 5,1) then start_theta_index=-155 + 300 means i=145

  switch (rot_axis)
  {
    case ROT_about_X:
    if (dir > 0) //move fwd about x-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis at pointer
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer
 
        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about x-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_X = (i-300); //keep track of current rotation angle for axis
        u1 = *rotation_theta_X/10 * Deg2RotX;   //Rx drives detector angle to point to rotation origin

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = c0;  //Ry
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;


    case ROT_about_Y:
    if (dir > 0) //move fwd about y-axis
    {
      for (i = start_theta_index; i < 601; i++)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to rotation center
        DoLinear(); //add linear segment to buffer 

        //set start pos to last pos for all axes
        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }

    else if (dir < 0) //move rev about y-axis
    {
      for (i = start_theta_index; i > 0; i--)
      {
        x1 = profile_3D_mat[i][x];   //Dx
        y1 = profile_3D_mat[i][y];   //Dy
        v1 = profile_3D_mat[i][z];   //Dz
        *rotation_theta_Y = (i-300); //keep track of current rotation angle for axis
        u1 = u0; //Ry

        z1 = z0;  //Sx
        a1 = a0;  //Sy
        b1 = b0;  //Sz
        c1 = *rotation_theta_Y/10 * Deg2RotY;   //Ry to point to center 
        DoLinear(); //add linear segment to buffer 
        //set start pos to last pos for all axes

        x0 = x1;
        y0 = y1;
        v0 = v1;
        u0 = u1;

        z0 = z1;
        a0 = a1;
        b0 = b1;
        c0 = c1;
      }
    }
    break;
  }

}

//---------function that runs motion

int amc_linear_move(void) // 
{
    DefineCoordSystem8(axis_0DX,ax is_1DY,axis_2SX,axis_3SY,axis_ 4SZ,axis_5RY,axis_6RX,axis_7DZ );
    VM = 600;
    A = 800;

   CS0_Flushed=TRUE;

  ExecBuf();

  while(!CheckDoneBuf() )
  {
    if(jogEnableFlag == 1 && *jogVelocity == 0) //condition to test if operator depressed rotation jog button
    {
      StopCoordinatedMotion();
      while(CS0_StoppingState < 3)
      {
        //wait until stop
      }
      ClearStopImmediately();

      jogEnableFlag = 0;
      break;
    }
  }
}


//-----commanding routine
int about_x=0,about_y=1,fwd=1,rev= -1;

profile_2D_pionts(); //run once upon startup

//function if x-axis rotation selected with plane tilted by 15.5 degrees
profile_3D_axis_rot_points(155 , about_x); //15.5 deg about x-axis

//move forward on profile
fill_buffer(about_x, 155, fwd);

amc_linear_move(); //execute buffer 

For simplicity and program execution efficiency, I can combine profile_3D_axis_rot_po ints() and fill_buffer() functions.  In fact in my code I have that. I just broke it up in this write up to make it clear.

Anyway, this approach will not work for me.  Although the motion seems to be giving me what I need, it seems that any direction of motion I select, either going forward or reverse in either about-x or about-y axis, it only goes in ONE direction.  Mainly the direction that is first initiated.  My guess is that when I stop the motion by invoking the StopCoordinatedMotion() function after releasing the button, it doesn't clear the buffer.  Any subsequent selection I make, causes the motion to continue  moving from where it left off.  I was under the impression that ClearStopImmediately() cleared any remaining elements in the buffer. 

Any thoughts?